package com.jeasy.security;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.lang3.StringUtils;

import com.jeasy.util.DataUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * @author taomk
 * @version 1.0
 * @since 2014/9/22 14:33
 */
@Slf4j
public final class MD5Utils {

	private static final String SEC_TYPE = "MD5";

	private MD5Utils() {
	}

	private static final char[] DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

	public static String md5(String inStr, String charset) {
		MessageDigest md5;
		try {
			md5 = MessageDigest.getInstance(SEC_TYPE);
		} catch (Exception e) {
			System.out.println(e.toString());
			log.error("error exception", e);
			return StringUtils.EMPTY;
		}
		byte[] byteArray;
		try {
			byteArray = inStr.getBytes(charset);
		} catch (UnsupportedEncodingException e) {
			return null;
		}

		return DataUtils.byteArr2HexStr(md5.digest(byteArray));
	}

	private static MessageDigest getDigest() {
		try {
			MessageDigest md5MessageDigest = MessageDigest.getInstance(SEC_TYPE);
			md5MessageDigest.reset();
			return md5MessageDigest;
		} catch (NoSuchAlgorithmException nsaex) {
			throw new RuntimeException("Could not access MD5 algorithm, fatal error");
		}
	}

	/**
	 * 计算content的md5摘要.
	 *
	 * @param content
	 * @return md5结果
	 */
	public static String md5(String content) {
		byte[] data = getDigest().digest(content.getBytes());
		return DataUtils.byteArr2HexStr(data);
	}

	public static String md5Sum(String inputStr) throws NoSuchAlgorithmException {
		MessageDigest digest = getDigest();
		byte[] inputStrByte = inputStr.getBytes();
		digest.update(inputStrByte, 0, inputStrByte.length);

		byte[] md5sum = digest.digest();

		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < 16; i++) {
			char[] ob = new char[2];
			ob[0] = DIGITS[md5sum[i] >> 4 & 0x0F];
			ob[1] = DIGITS[md5sum[i] & 0x0F];
			String s = new String(ob);
			sb.append(s);
		}

		return sb.toString();
	}

	/**
	 * 签名字符串
	 *
	 * @param text 需要签名的字符串
	 * @param sign 签名结果
	 * @return 签名结果
	 */
	public static boolean verify(String text, String sign) {
		String mysign = md5(text);
		if (mysign.equals(sign)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 对文件进行 MD5 加密
	 *
	 * @param file 待加密的文件
	 * @return 文件加密后的 MD5 值
	 * @throws java.io.IOException
	 */
	public static String md5(File file) throws IOException {
		FileInputStream is = new FileInputStream(file);
		MessageDigest md5 = null;
		try {
			md5 = MessageDigest.getInstance(SEC_TYPE);
			int n = 0;
			byte[] buffer = new byte[1024];
			do {
				n = is.read(buffer);
				if (n > 0) {
					md5.update(buffer, 0, n);
				}
			} while (n != -1);
			is.skip(0);
		} catch (NoSuchAlgorithmException e) {
			log.error("error exception", e);
			throw new RuntimeException(e.getMessage());
		} finally {
			is.close();
		}

		byte[] encodedValue = md5.digest();

		int j = encodedValue.length;
		char finalValue[] = new char[j * 2];
		int k = 0;
		for (int i = 0; i < j; i++) {
			byte encoded = encodedValue[i];
			finalValue[k++] = DIGITS[encoded >> 4 & 0xf];
			finalValue[k++] = DIGITS[encoded & 0xf];
		}

		return new String(finalValue);
	}
}
